Summary
data <- read.csv('./mp_batteries.csv')
prettyTable(data)
Sprawdźmy czy potrzebne będzie usunięcie wartości pustych.
for (name in colnames(data)){
isMissing <- sum(is.na(data[[name]]))
if (isMissing == 0) {
print(paste('Brak wartości pustych dla', name))
} else {
print(paste(name, 'posiada :', isMissing, 'wartości puste', sep=' '))
}
}
## [1] "Brak wartości pustych dla Battery.ID"
## [1] "Brak wartości pustych dla Battery.Formula"
## [1] "Brak wartości pustych dla Working.Ion"
## [1] "Brak wartości pustych dla Formula.Charge"
## [1] "Brak wartości pustych dla Formula.Discharge"
## [1] "Brak wartości pustych dla Max.Delta.Volume"
## [1] "Brak wartości pustych dla Average.Voltage"
## [1] "Brak wartości pustych dla Gravimetric.Capacity"
## [1] "Brak wartości pustych dla Volumetric.Capacity"
## [1] "Brak wartości pustych dla Gravimetric.Energy"
## [1] "Brak wartości pustych dla Volumetric.Energy"
## [1] "Brak wartości pustych dla Atomic.Fraction.Charge"
## [1] "Brak wartości pustych dla Atomic.Fraction.Discharge"
## [1] "Brak wartości pustych dla Stability.Charge"
## [1] "Brak wartości pustych dla Stability.Discharge"
## [1] "Brak wartości pustych dla Steps"
## [1] "Brak wartości pustych dla Max.Voltage.Step"
Nasz zestaw nie zawiera wartości pustych.
Zbiór danych składa się z 4351 rekordów. Każdy rekord posiada 12 wartości numerycznych, 4 tekstowe i id. Podsumujemy wartości nienumeryczne. Jedyna wartość, która nas będzie interesować to ilość unikatowych wartości.
textSummary <- data %>%
select(Battery.Formula:Formula.Discharge) %>%
summarise(across(everything(), n_distinct, .names = 'unique {.col}'))
textSummary %>% knitr::kable()
| unique Battery.Formula | unique Working.Ion | unique Formula.Charge | unique Formula.Discharge |
|---|---|---|---|
| 3301 | 10 | 2096 | 3173 |
Jedyna przydatna dla nas kolumna to Working.Ion.
Podsumujmy teraz wartości numeryczne.
summaryDf <- data.frame(
mean = numeric(),
median = numeric(),
min = numeric(),
max = numeric(),
sd = numeric()
)
colNames <- data %>%
select(Max.Delta.Volume:Max.Voltage.Step) %>% colnames()
for (col in colNames) {
column <- data[col]
res <- column %>% summarise(
across(everything(),
c(mean, median, min, max, sd)
)
)
colnames(res) <- c('mean', 'median', 'min', 'max', 'sd')
summaryDf <- rbind(summaryDf, res)
}
rownames(summaryDf) <- colNames
summaryDf %>% knitr::kable()
| mean | median | min | max | sd | |
|---|---|---|---|---|---|
| Max.Delta.Volume | 0.3753137 | 0.0420271 | 0.0000162 | 2.931932e+02 | 6.8518375 |
| Average.Voltage | 3.0831427 | 3.3005818 | -7.7547512 | 5.456883e+01 | 1.8220562 |
| Gravimetric.Capacity | 158.2908894 | 130.6909797 | 5.1765430 | 2.557627e+03 | 164.9136411 |
| Volumetric.Capacity | 610.6240987 | 507.0312049 | 24.0790699 | 7.619191e+03 | 563.8531258 |
| Gravimetric.Energy | 444.1063802 | 401.7876573 | -583.5458444 | 5.926950e+03 | 351.0481297 |
| Volumetric.Energy | 1664.0484137 | 1463.7877150 | -2208.0745659 | 1.830590e+04 | 1297.7985678 |
| Atomic.Fraction.Charge | 0.0398558 | 0.0000000 | 0.0000000 | 9.090909e-01 | 0.0885604 |
| Atomic.Fraction.Discharge | 0.1590772 | 0.1428571 | 0.0074074 | 9.933333e-01 | 0.1203743 |
| Stability.Charge | 0.1425666 | 0.0731920 | 0.0000000 | 6.487098e+00 | 0.3782776 |
| Stability.Discharge | 0.1220717 | 0.0487845 | 0.0000000 | 6.277809e+00 | 0.3523182 |
| Steps | 1.1670880 | 1.0000000 | 1.0000000 | 6.000000e+00 | 0.4637496 |
| Max.Voltage.Step | 0.1502897 | 0.0000000 | 0.0000000 | 2.696069e+01 | 0.6300680 |
Przyjrzyjmy się dokładniej rozkładom wartości numerycznym. Wszystkie przypominają rozkład normalny, który jest silnie skoncentrowany wokół mediany. Większość rozkładów posiada kilka wartości skrajnych. Working.Ion ma dominującą wartość - Li.
excludeHist <- c("Battery.ID","Battery.Formula", "Formula.Charge", "Formula.Discharge", "Working.Ion" ,"Max.Delta.Volume")
histData <- data[ , !(names(data) %in% excludeHist)]
colNames <- histData %>% colnames()
#
for (column in colNames) {
minVal <- summaryDf[column, 'min']
maxVal <- summaryDf[column, 'max']
bins <- (maxVal - minVal) / 100
graph <- histData %>% ggplot(aes_string(x = column)) +
geom_histogram(fill = 'blue', binwidth = bins) +
labs(title = paste(column, ' histogram'), x = column, y = 'Frequency') +
theme_minimal()
plot(graph)
}
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
graph <- data %>% ggplot(aes(x = Max.Delta.Volume)) +
geom_histogram(binwidth = 0.01, fill = 'blue', ) +
labs(title = 'Histogram of Max.Delta.Volume', x = 'Max.Delta.Volume', y = 'Frequency') +
xlim(-0.1, 1.5) + theme_minimal()
plot(graph)
## Warning: Removed 65 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_bar()`).
graph <- data.frame(table(data$Working.Ion)) %>% ggplot(aes(x = Var1, y = Freq)) +
geom_col(fill = 'blue') +
labs(title = 'Working Ion histogram', y = 'Frequency', x ='Ion') +
theme_minimal()
plot(graph)
Przyjrzyjmy się korelacjom między wartościami. Występuje kilka korelacji wartych dalszej analizy - Charge/Discharge pairs, energy, capacity.
cor_matrix <- cor(data %>% select_if(is.numeric), method = "pearson")
cor_data <- melt(cor_matrix)
corr <- cor_data %>%
ggplot(aes(x = Var1, y = Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(
low = "blue",
mid = "white",
high = "red",
midpoint = 0,
limits = c(-1, 1)
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
coord_fixed() +
labs(title = "Correlation Matrix", x = "Fields", y = "Fields")
#ggplotly(corr)
plot(corr)
Zależność pomiędzy Average Voltage i Gravimetric Energy jest gorzej
widoczna przez obecność wartości skrajnych na wykresie. Po usunięciu
outlierów widzimy
data %>% ggplot(aes(x = Average.Voltage, y=Gravimetric.Energy)) +
geom_point(color = "blue") + # Scatter points
geom_smooth(method = "lm") + # Regression line
labs(title = "Average Voltage and Gravimetric Energy",
x = "Avg. Voltage",
y = "Gravimetric Energy") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
data %>%
filter(Average.Voltage < 30) %>%
ggplot(aes(x = Average.Voltage, y=Gravimetric.Energy)) +
geom_point(color = "blue") + # Scatter points
geom_smooth(method = "lm") + # Regression line
labs(title = "Average Voltage and Gravimetric Energy without outliers",
x = "Avg. Voltage",
y = "Gravimetric Energy") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
data %>% ggplot(aes(x = Atomic.Fraction.Discharge, y=Gravimetric.Capacity)) +
geom_point(color = "blue") + # Scatter points
geom_smooth() + # Regression line
geom_smooth(method = "lm") + # Regression line
labs(title = "Atomic Fraction Discharge and Gravimetric Capacity",
x = "Atomic Fraction Discharge",
y = "Gravimetric Capacity") +
theme_minimal()
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'
## `geom_smooth()` using formula = 'y ~ x'
data %>% ggplot(aes(x = Atomic.Fraction.Discharge, y=Volumetric.Capacity)) +
geom_point(color = "blue") + # Scatter points
geom_smooth(method = "lm") + # Regression line
labs(title = "Atomic Fraction Discharge and Volumetric Capacity",
x = "Atomic Fraction Discharge",
y = "Volumetric Capacity") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'